home *** CD-ROM | disk | FTP | other *** search
/ Precision Software Appli…tions Silver Collection 1 / Precision Software Applications Silver Collection Volume One (PSM) (1993).iso / tutor / asm1tut.exe / CHAP09.DOC < prev    next >
Text File  |  1990-06-22  |  25KB  |  625 lines

  1.  
  2.  
  3.  
  4.                                                                             68
  5.  
  6.                                    CHAPTER 9 - JUMPS
  7.  
  8.              So far we have done almost exclusively sequential programming -
  9.              the order of execution has been from one instruction to the next
  10.              until the very end, where the jump instruction has brought us
  11.              back to the top. This is not the normal way programs work. In
  12.              order to have things like DO loops, FOR loops, WHILE loops, CASE
  13.              constructions and IF-THEN-ELSE constructs, we need to make
  14.              decisions and to be able to go to different blocks of code
  15.              depending on our decisions.
  16.  
  17.              Intel has provided a wealth of conditional jumps to answer all
  18.              our needs. All of them are listed in a summary at the end of this
  19.              chapter.
  20.  
  21.              The thing we will do most often is compare the size of two
  22.              numbers. In BASIC code:
  23.  
  24.                  IF   A < B  THEN
  25.  
  26.              we need to see if A < B . If that is true, we do one thing, if it
  27.              is false, we do something else. One thing that we need to watch
  28.              out for is whether A and B are signed or unsigned numbers. Let A
  29.              = F523h (signed -2781; unsigned 62755) and B = 59E0h (signed
  30.              +23008; unsigned 23008). If A and B are signed numbers, then A <
  31.              B. However, if they are unsigned numbers, then  A > B. In C and
  32.              PASCAL, the compiler takes care of whether you want signed or
  33.              unsigned numbers (BASIC assumes that it is always signed
  34.              numbers). You are now on the machine level, and must take care of
  35.              this yourself. 
  36.  
  37.              To compare two numbers, you subtract one from the other, and then
  38.              evaluate the result (less than 0,  0, or more than 0). To compare
  39.              A and B, you do A minus B. To compare AX and BX, you can:
  40.  
  41.                  sub  ax, bx
  42.  
  43.              and then evaluate it. Unfortunately, if you do that, you will
  44.              destroy the information in AX. It will have been changed in the
  45.              process. Intel has solved this problem with the CMP (compare)
  46.              instruction. 
  47.  
  48.                  cmp  ax, bx
  49.  
  50.              subtracts BX from AX, sets the flags, and throws the answer away.
  51.              CMP is exactly the same as SUB except that AX remains unchanged.
  52.              We probably don't want to save the result anyway. If we do, we
  53.              can always use:
  54.  
  55.                  sub  ax, bx
  56.  
  57.              We have subtracted BX from AX. There are now three possibilities.
  58.              (1) AX > BX so the answer is positive, (2) AX = BX so the answer
  59.              is zero, or (3) AX < BX so the answer is negative. But are these
  60.  
  61.              ______________________
  62.  
  63.              The PC Assembler Tutor - Copyright (C) 1989 Chuck Nelson
  64.  
  65.  
  66.  
  67.  
  68.              Chapter 9 - Jumps                                              69
  69.              _________________
  70.  
  71.              signed or unsigned numbers? The 8086 uses the same subtract (or
  72.              CMP) instruction for both signed or unsigned numbers. You have to
  73.              tell the 8086 in the following instruction whether you were
  74.              talking about signed or unsigned numbers.
  75.  
  76.                  cmp  ax, bx
  77.                  ja   some_label
  78.  
  79.              asks the machine to compare AX and BX. It then says that AX and
  80.              BX were UNSIGNED numbers and the machine should jump to
  81.              "some_label" if AX was above BX.
  82.  
  83.                  cmp  ax, bx
  84.                  jg   some_label
  85.  
  86.              asks the machine to compare AX and BX. It then says that AX and
  87.              BX were SIGNED numbers and the machine should jump to
  88.              "some_label" if AX was greater than BX.
  89.  
  90.              The 8086 makes the decision by looking at the flags. They give it
  91.              complete information about the result. (The decision making rules
  92.              are in the summary).
  93.  
  94.              In our example on the previous page, we had A = -2781 (unsigned
  95.              62755) and B = +23008 (unsigned 23008). If we put A in AX and B
  96.              in BX, then the instruction JA will execute the jump, while the
  97.              instruction JG will not execute the jump. What happens if the
  98.              8086 doesn't execute the jump? It goes on to the next
  99.              instruction.
  100.  
  101.              As I said before, the 8086 has LOTS of conditional jumps. I am
  102.              going to give you a list of them now, but be forewarned that the
  103.              mnemonics for these suckers are confusing. Rather than doing
  104.              something sensible like JUG for 'jump unsigned greater' and JSG
  105.              for 'jump signed greater' - things that would be easy to
  106.              distinguish, they have JA for 'jump above' (unsigned) and JG for
  107.              'jump greater' (signed).{1}  Therefore, use the summary at the
  108.              end of the chapter. With enough use, you will remember which is
  109.              which. 
  110.  
  111.              The arithmetic jump instructions have two forms, a positive one
  112.              and a negative one. For instance:
  113.  
  114.                  ja        ; jump above
  115.                  jnbe      ; jump not (below or equal)
  116.  
  117.              are actually the same machine instruction. You use whichever one
  118.              makes the program clearer. We will have examples later to
  119.              illustrate both positive and negative mnemonics. Here are the
  120.              signed and unsigned instructions and their meaning. The
  121.              ____________________
  122.  
  123.                 1 This wierd use of the words above and greater, below and
  124.              less, is so confusing that my copy of the Microsoft assembler
  125.              manual v5.1 has it reversed on one page. It calls the signed
  126.              jumps unsigned and the unsigned jumps signed. And that's the one
  127.              place where it SHOULD be right.
  128.  
  129.  
  130.  
  131.  
  132.              The PC Assembler Tutor                                         70
  133.              ______________________
  134.  
  135.              equivalent mnemonics will appear in pairs.
  136.  
  137.              THESE ARE THE SIGNED JUMP INSTRUCTIONS
  138.  
  139.                  jg        ; jump if greater
  140.                  jnle      ; jump if not (less or equal){2}
  141.  
  142.                  jl        ; jump if less
  143.                  jnge      ; jump if not (greater or equal)
  144.  
  145.                  je        ; jump if equal
  146.                  jz        ; jump if zero 
  147.  
  148.                  jge       ; jump if greater or equal
  149.                  jnl       ; jump if not less
  150.  
  151.                  jle       ; jump if less or equal
  152.                  jng       ; jump if not greater
  153.  
  154.                  jne       ; jump if not equal
  155.                  jnz       ; jump if not zero 
  156.  
  157.              These are self-explainatory, keeping in mind that these apply
  158.              only to signed numbers.
  159.  
  160.  
  161.              THESE ARE THE UNSIGNED JUMP INSTRUCTIONS
  162.  
  163.                  ja        ; jump if above
  164.                  jnbe      ; jump if not (below or equal) 
  165.  
  166.                  jb        ; jump if below
  167.                  jnae      ; jump if not (above or equal) 
  168.  
  169.                  je        ; jump if equal
  170.                  jz        ; jump if zero 
  171.  
  172.                  jae       ; jump if above or equal
  173.                  jnb       ; jump if not below 
  174.  
  175.                  jbe       ; jump if below or equal
  176.                  jna       ; jump if not above
  177.  
  178.                  jne       ; jump if not equal
  179.                  jnz       ; jump if not zero 
  180.  
  181.              These apply to unsigned numbers, and should be clear. 
  182.  
  183.              JZ, JNZ, JE and JNE work for both signed and unsigned numbers.
  184.              After all, zero is zero.
  185.              ____________________
  186.  
  187.                 2 I was trying to decide whether or not to put in the
  188.              parentheses. If there are two things after the "not" the "not"
  189.              applies to both of them. By the rules of logic, not (less or
  190.              equal) == not less AND not equal. If you don't understand this,
  191.              try to find someone who can explain it to you. 
  192.  
  193.  
  194.  
  195.  
  196.              Chapter 9 - Jumps                                              71
  197.              _________________
  198.  
  199.  
  200.              Before we get going, there is one more thing you need to know.
  201.              The unconditional jump:
  202.  
  203.                  jmp  some_label
  204.  
  205.              can jump anywhere in the current code segment. XXXX is the
  206.              current number in CS, then jmp can go from XXXX offset 0 to XXXX
  207.              offset 65535.
  208.  
  209.              Conditional jumps are something else entirely. ALL conditional
  210.              jumps (including the loop instruction) are limited range jumps.
  211.              They are from -128 to +127. That is, they can go backward up to
  212.              128 bytes and they can go forward up to 127 bytes.{3} You will
  213.              find that you will get assembler errors because the conditional
  214.              jumps are too far away, but don't worry because we can ALWAYS fix
  215.              them. You will find out later how to deal with them. 
  216.  
  217.  
  218.              As in the other arithmetic instructions, there are five forms of
  219.              the CMP instruction.
  220.  
  221.                  1.   compare two registers
  222.                  2.   compare a register with a variable
  223.                  3.   compare a variable with a register
  224.                  4.   compare a register with a constant
  225.                  5.   compare a variable with a constant
  226.  
  227.              These look like:
  228.  
  229.                  cmp  ah, dl
  230.                  cmp  si, memory_data
  231.                  cmp  memory_data, ax
  232.                  cmp  ch, 127
  233.                  cmp  memory_data, 14938
  234.  
  235.  
  236.              Here are some decisions we might have to make in programs. 
  237.  
  238.              (1) We are writing a program to print hex numbers on the screen.
  239.              We have one routine for 0 - 9 and a different one for A - F.
  240.              Sound familiar?
  241.  
  242.                  cmp  al, 10
  243.                  jb   decimal_routine
  244.                  ; here we are past the jump, so we can start the  A - F
  245.                  ; routine.
  246.  
  247.              (2) We want to fire everyone over the age of 55 (this is an
  248.              unsigned number since there are no negative ages):
  249.              ____________________
  250.  
  251.                 3 But they don't jump from the beginning of the machine
  252.              instruction, they jump from the END of the machine instruction
  253.              (which is two bytes long). This means that they have an effective
  254.              range of from -126 bytes to +129 bytes from the BEGINNING of the
  255.              instruction.
  256.  
  257.  
  258.  
  259.  
  260.              The PC Assembler Tutor                                         72
  261.              ______________________
  262.  
  263.  
  264.                  cmp  employee_age, 55
  265.                  ja   find_a_reason_for_termination
  266.                  ; start of routine for younger employees here.
  267.  
  268.              (3) You want to know if you need to go to a loanshark:
  269.  
  270.                  mov  di, bank_balance
  271.                  cmp  unpaid_bills, di
  272.                  jg   gotta_go_see_Vinnie
  273.                  ; continue normal routine here
  274.  
  275.              (4) Notice that the last one could have also been written:
  276.  
  277.                  mov  di, bank_balance
  278.                  cmp  di, unpaid_bills
  279.                  jl   gotta_go_see_Vinnie
  280.                  ; continue normal routine
  281.  
  282.              though to my eye the first one seems clearer.
  283.  
  284.              (5) You have the results from two calculations, the first one in
  285.              DI and the second one in CX. You need to go to different routines
  286.              depending on which is larger. If they are the same, you exit:
  287.  
  288.                  cmp  di, cx
  289.                  jg   routine_one         ; di is greater
  290.                  jl   routine_two         ; cx is greater
  291.                  jmp  exit_label          ; they are equal
  292.  
  293.              We had two conditional jumps in a row and both of them were able
  294.              to look at the results of the CMP instruction because the first
  295.              jump (JG) did not change any of the flags. This is true of all
  296.              jumps - conditional jumps, the unconditional jump, and LOOP. They
  297.              never change any of the flags, so you can have two jumps in a row
  298.              and be certain that the flags will not be altered.
  299.  
  300.  
  301.              (6) Your dad has promised to buy you a Corvette if you don't get
  302.              suspended from school more than three times this semester. Here's
  303.              his decision code:
  304.  
  305.                  cmp  number_of_suspensions, 3
  306.                  jng  buy_him_the_corvette
  307.                  ; better luck next time
  308.  
  309.  
  310.  
  311.              JUMP OUT OF RANGE
  312.  
  313.              If the code you are jumping to is more than -128 or +127 bytes
  314.              from the end of a conditional jump, you will get an assembler
  315.              error that the jump is out of range. This can always be fixed.
  316.              Take this code:
  317.  
  318.  
  319.  
  320.  
  321.  
  322.              Chapter 9 - Jumps                                              73
  323.              _________________
  324.  
  325.                       cmp  ax, bx
  326.                       jg   destination_label
  327.                  further_code:
  328.                       ; continue the program 
  329.  
  330.              If 'destination_label' is out of range, what you need to do is
  331.              jump to 'further_code' with a conditional jump (you are within
  332.              range of 'further_code') and use JMP (which can go anywhere in
  333.              the segment) to go to 'destination_label'. To switch the jump,
  334.              you simply negate the jump condition:
  335.  
  336.                  jg   ->   jng
  337.                  je   ->   jne
  338.                  jne  ->   je
  339.                  jbe  ->   jnbe
  340.  
  341.              We use reverse logic. Originally, if the condition was met we
  342.              jumped. If the condition was not met we continued. Now, if the
  343.              condition is NOT met, we jump, and if the condition is NOT not
  344.              met (yes, there are two NOTs) which means it was met, we
  345.              continue, and this sends us to the JMP instruction. Make sure you
  346.              believe this works correctly before going on. The code then looks
  347.              like this:
  348.  
  349.                       cmp  ax, bx
  350.                       jng  further_code
  351.                       jmp  destination_label
  352.                  further_code:
  353.                       ; continue the program
  354.  
  355.              This is the standard way of handling the situation.
  356.  
  357.  
  358.  
  359.  
  360.  
  361.  
  362.  
  363.  
  364.  
  365.  
  366.  
  367.  
  368.  
  369.  
  370.  
  371.  
  372.  
  373.  
  374.  
  375.  
  376.  
  377.  
  378.  
  379.  
  380.  
  381.  
  382.  
  383.  
  384.  
  385.  
  386.              The PC Assembler Tutor                                         74
  387.              ______________________
  388.  
  389.                                         SUMMARY
  390.  
  391.              CMP
  392.                  CMP performs the same operation as subtraction, but it does
  393.              not change the registers or variables, it only sets the flags. It
  394.              is the cousin of TEST. As usual, there are five possibilities:
  395.  
  396.                  1.   compare two registers
  397.                  2.   compare a register with a variable
  398.                  3.   compare a variable with a register
  399.                  4.   compare a register with a constant
  400.                  5.   compare a variable with a constant
  401.  
  402.  
  403.              THESE ARE THE SIGNED JUMP INSTRUCTIONS
  404.  
  405.                  jg        ; jump if greater
  406.                  jnle      ; jump if not (less or equal) 
  407.  
  408.                  jl        ; jump if less
  409.                  jnge      ; jump if not (greater or equal) 
  410.  
  411.                  je        ; jump if equal
  412.                  jz        ; jump if zero 
  413.  
  414.                  jge       ; jump if greater or equal
  415.                  jnl       ; jump if not less
  416.  
  417.                  jle       ; jump if less or equal
  418.                  jng       ; jump if not greater
  419.  
  420.                  jne       ; jump if not equal
  421.                  jnz       ; jump if not zero 
  422.  
  423.  
  424.  
  425.              THESE ARE THE UNSIGNED JUMP INSTRUCTIONS
  426.  
  427.                  ja        ; jump if above
  428.                  jnbe      ; jump if not (below or equal) 
  429.  
  430.                  jb        ; jump if below
  431.                  jnae      ; jump if not (above or equal) 
  432.  
  433.                  je        ; jump if equal
  434.                  jz        ; jump if zero 
  435.  
  436.                  jae       ; jump if above or equal
  437.                  jnb       ; jump if not below 
  438.  
  439.                  jbe       ; jump if below or equal
  440.                  jna       ; jump if not above
  441.  
  442.                  jne       ; jump if not equal
  443.                  jnz       ; jump if not zero 
  444.  
  445.  
  446.  
  447.  
  448.  
  449.  
  450.              Chapter 9 - Jumps                                              75
  451.              _________________
  452.  
  453.              THESE JUMPS CHECK A SINGLE FLAG 
  454.  
  455.              These come in opposite pairs
  456.  
  457.                  jc        ; jump if the carry flag is set
  458.                  jnc       ; jump if the carry flag is not set
  459.  
  460.                  jo        ; jump if the overflow flag is set
  461.                  jno       ; jump if the overflow flag is not set
  462.  
  463.                  jp or jpe ; jump if parity flag is set (parity is even)
  464.                  jnp or jpo  ;jump if parity flag is not set (parity is odd)
  465.  
  466.  
  467.                  js        ; jump if the sign flag is set (negative )
  468.                  jns       ; jump if the sign flag is not set (positive or 0)
  469.  
  470.  
  471.              THIS CHECKS THE CX REGISTER
  472.  
  473.                  jcxz      ; jump if cx is zero
  474.  
  475.              Why do we have this instruction? Remember, the loop instruction
  476.              decrements CX and then checks for 0. If you enter a loop with CX
  477.              set to zero, the loop will repeat 65536 times. Therefore, if you
  478.              don't know what the value of CX will be when you enter the loop,
  479.              you use this instruction just before the loop to skip the loop if
  480.              CX is zero:
  481.  
  482.                       jcxz after_the_loop
  483.  
  484.                  loop_start:
  485.                            .
  486.                            .
  487.                            .
  488.                            .
  489.                       loop loop_start
  490.                  after_the_loop:
  491.  
  492.  
  493.              INFORMATION ABOUT JUMPS
  494.  
  495.              The unconditional jump (JMP) can go anywhere in the code segment.
  496.              All other jumps, which are conditional, can only go from -128 to
  497.              +127 bytes from the END of the jump instruction (that's from -126
  498.              to +129 bytes from the beginning of the instruction).
  499.  
  500.              Jumps have no effect on the 8086 flags.
  501.  
  502.              How does the 8086 decide whether something is more, less, or the
  503.              same? The rules for unsigned numbers are easy. If you subtract a
  504.              larger number from a smaller, the subtraction will pass through
  505.              zero and will set the carry flag (CF). If they are the same, the
  506.              result will be zero and it will set the zero flag (ZF). If the
  507.              first number is larger, the machine will clear the carry flag and
  508.              the zero flag will be cleared (ZF = 0). Therefore, for unsigned
  509.              numbers, we have:
  510.  
  511.  
  512.  
  513.  
  514.              The PC Assembler Tutor                                         76
  515.              ______________________
  516.  
  517.  
  518.              First number is:
  519.                  above          CF = 0    ZF = 0
  520.                  equal          CF = 0    ZF = 1
  521.                  not equal      CF = ?    ZF = 0
  522.                  below          CF = 1    ZF = 0
  523.  
  524.              All other unsigned compares are combinations of those three
  525.              things:
  526.  
  527.                  jae  = ja OR je     (CF = 0 and ZF = 0) or ZF = 1
  528.                  jbe  = jb OR je     CF = 1 or ZF = 1
  529.  
  530.              When you have a negative condition, it is much easier to look at
  531.              its equivalent positive condition to figure out what is going on:
  532.  
  533.                  jnae   is the same as    jb   CF = 1
  534.                  jnbe   is the same as    ja   CF = 0    ZF = 0
  535.  
  536.  
  537.              SIGNED NUMBERS
  538.  
  539.              This section is not for the fainthearted. It is not necessary, so
  540.              if you find yourself getting confused, just remember that if you
  541.              see documentation talking about a jump where the overflow flag
  542.              equals the sign flag or the overflow flag doesn't equal the sign
  543.              flag, it is talking about SIGNED numbers.
  544.  
  545.              Zero is zero, so we won't concern ourselves with it here. It is
  546.              exactly the same.
  547.  
  548.              If A and B are two signed word sized numbers and we have:
  549.  
  550.                  cmp  A, B
  551.  
  552.              then we can have four different cases:
  553.  
  554.                  1) If A is just a little greater than B  [(A - B) <=
  555.                  +32767],  then the result will be a small positive number,
  556.                  and there will be no overflow. SF = 0, OF = 0.
  557.  
  558.                  2) If A is much greater than B [+32767 < (A - B)], then the
  559.                  result will be too positive and it will overflow from
  560.                  positive to negative. This will set both the sign flag (it
  561.                  is now negative) and the overflow flag. SF = 1, OF = 1.
  562.  
  563.                  3) If A is a little less than B [-32768 <= (A - B)], that is
  564.                  if it is only a little negative, then the result is a small
  565.                  negative number, and there is no overflow. SF = 1, OF = 0.
  566.  
  567.                  4) If A is much less than B [(A - B) < -32768], then the
  568.                  result is a large negative number. It is too negative and
  569.                  overflows into a positive number. SF = 0, OF = 1.
  570.  
  571.              Recapping, for a positive result:
  572.  
  573.                  1) SF = 0, OF = 0
  574.  
  575.  
  576.  
  577.  
  578.              Chapter 9 - Jumps                                              77
  579.              _________________
  580.  
  581.                  2) SF = 1, OF = 1
  582.  
  583.              and for a negative result:
  584.  
  585.                  3) SF = 1, OF = 0
  586.                  4) SF = 0, OF = 1
  587.  
  588.              For positive results (and zero), SF = OF. For negative results,
  589.              SF is not equal to OF. This, in fact, is how the 8086 decides a
  590.              signed jump. If SF = OF, it's positive, if SF is not equal to OF,
  591.              it's negative. If ZF = 1, then obviously they are equal. Here is
  592.              the list:
  593.  
  594.                  greater        SF = OF   ZF = 0
  595.                  equal          SF = OF   ZF = 1
  596.                  not equal                ZF = 0
  597.                  less           SF is not equal to OF
  598.  
  599.              As with the unsigned numbers, if you have a negative condition,
  600.              it is easier to change it into its equivalent positive condition
  601.              and then figure out the requirements. For instance:
  602.  
  603.                  jnge      same as   jl   SF is not equal to OF
  604.                  jnl       same as   jge  ( SF = OF and ZF = 0 ) or ( ZF = 1)
  605.  
  606.              If you think about it, this OF = SF stuff does make sense. We are
  607.              subtracting two numbers. If the first one is greater, then the
  608.              answer will be positive. It can either be a little positive as in
  609.              (cmp 0, -1 ) = 1 or it can be very positive, as in (cmp 32767,
  610.              -32768) = 65,535 (same as -1). If it is just a little positive,
  611.              there is no overflow and it has a positive sign (SF = 0, OF = 0).
  612.              If the difference gets large, then the number overflows from + to
  613.              -. At that point OF = 1, but it now has a negative sign, so OF =
  614.              SF. The flags MUST match.
  615.  
  616.              In the opposite case where the second number is greater, The
  617.              answer is negative. It can either be a little negative as in (cmp
  618.              12, 13)= -1, or it can be very negative (cmp -32768, 32767) =
  619.              -65535 =1. If it is a small difference, the sign is negative, but
  620.              there is no overflow (SF = 1, OF = 0). As the difference gets
  621.              larger, the number overflows from negative to positive so the
  622.              sign flag is now positive, but the overflow flag is set (SF = 0,
  623.              OF = 1). Those flags CAN'T match.
  624.  
  625.